package com.chaintor.demo.math;

import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math3.analysis.solvers.AbstractUnivariateDifferentiableSolver;
import org.apache.commons.math3.exception.TooManyEvaluationsException;
import org.apache.commons.math3.util.FastMath;

//自实现牛顿迭代不报TooManyEvaluationsException错，当TooManyEvaluationsException时返回结果值
public class NoTooManyNewtonRaphsonSolver extends AbstractUnivariateDifferentiableSolver {
    private static final double DEFAULT_ABSOLUTE_ACCURACY = 1.0E-6D;

    public NoTooManyNewtonRaphsonSolver(){
        this(DEFAULT_ABSOLUTE_ACCURACY);
    }

    public NoTooManyNewtonRaphsonSolver(double absoluteAccuracy){
        super(absoluteAccuracy);
    }

    //重写迭代方法去除错误返回
    protected double doSolve() throws TooManyEvaluationsException {
        double startValue = getStartValue();
        double absoluteAccuracy = getAbsoluteAccuracy();

        double x0 = startValue;
        double x1;
        while (true) {
            try {
                final DerivativeStructure y0 = computeObjectiveValueAndDerivative(x0);
                x1 = x0 - (y0.getValue() / y0.getPartialDerivative(1));
                if (FastMath.abs(x1 - x0) <= absoluteAccuracy) {
                    return x1;
                }

                x0 = x1;
            }catch (TooManyEvaluationsException e){
                return x0;
            }
        }
    }
}
